const Bull = require('bull');
const config = require('../config');
const { logger } = require('../utils/logger');

class QueueService {
  constructor() {
    this.queues = {};
    this.defaultConfig = {
      redis: {
        host: config.redis.host,
        port: config.redis.port,
        password: config.redis.password
      },
      defaultJobOptions: {
        attempts: 3,
        backoff: {
          type: 'exponential',
          delay: 1000
        },
        removeOnComplete: true
      }
    };
  }

  /**
   * 创建队列
   * @param {string} name - 队列名称
   * @param {Function} processor - 处理器
   * @param {Object} options - 选项
   * @returns {Bull} - 创建的队列
   */
  createQueue(name, processor, options = {}) {
    if (this.queues[name]) {
      return this.queues[name];
    }

    const queue = new Bull(name, {
      ...this.defaultConfig,
      ...options
    });

    queue.process(processor);

    // Event handlers
    queue.on('error', (error) => {
      logger.error(`Queue ${name} error:`, error);
    });

    queue.on('failed', (job, error) => {
      logger.error(`Job ${job.id} in queue ${name} failed:`, error);
    });

    queue.on('completed', (job) => {
      logger.info(`Job ${job.id} in queue ${name} completed`);
    });

    this.queues[name] = queue;
    return queue;
  }

  /**
   * 添加任务
   * @param {string} queueName - 队列名称
   * @param {Object} data - 任务数据
   * @param {Object} options - 选项
   * @returns {Promise<Object>} - 添加的任务
   */
  async addJob(queueName, data, options = {}) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    const job = await queue.add(data, options);
    return job;
  }

  /**
   * 获取任务
   * @param {string} queueName - 队列名称
   * @param {string} jobId - 任务ID
   * @returns {Promise<Object>} - 获取的任务
   */
  async getJob(queueName, jobId) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    return await queue.getJob(jobId);
  }

  /**
   * 移除任务
   * @param {string} queueName - 队列名称
   * @param {string} jobId - 任务ID
   * @returns {Promise<boolean>} - 移除结果
   */
  async removeJob(queueName, jobId) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    const job = await queue.getJob(jobId);
    if (job) {
      await job.remove();
      return true;
    }
    return false;
  }

  /**
   * 获取队列状态
   * @param {string} queueName - 队列名称
   * @returns {Promise<Object>} - 队列状态
   */
  async getQueueStatus(queueName) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    const [waiting, active, completed, failed] = await Promise.all([
      queue.getWaitingCount(),
      queue.getActiveCount(),
      queue.getCompletedCount(),
      queue.getFailedCount()
    ]);

    return {
      waiting,
      active,
      completed,
      failed
    };
  }

  /**
   * 暂停队列
   * @param {string} queueName - 队列名称
   */
  async pauseQueue(queueName) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    await queue.pause();
  }

  /**
   * 恢复队列
   * @param {string} queueName - 队列名称
   */
  async resumeQueue(queueName) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    await queue.resume();
  }

  /**
   * 清理队列
   * @param {string} queueName - 队列名称
   * @param {number} grace - 清理时间
   */
  async cleanQueue(queueName, grace = 1000) {
    const queue = this.queues[queueName];
    if (!queue) {
      throw new Error(`Queue ${queueName} not found`);
    }

    await queue.clean(grace);
  }

  /**
   * 获取队列
   * @param {string} queueName - 队列名称
   * @returns {Bull} - 队列
   */
  getQueue(queueName) {
    return this.queues[queueName];
  }

  /**
   * 获取所有队列
   * @returns {Object} - 所有队列
   */
  getAllQueues() {
    return this.queues;
  }
}

module.exports = new QueueService(); 